﻿namespace UnityEditor
{
    using System;
    using UnityEngine;

    [Serializable]
    internal class CurveEditorWindow : EditorWindow
    {
        [SerializeField]
        private GUIView delegateView;
        private const int kPresetsHeight = 0x2e;
        private Color m_Color;
        private AnimationCurve m_Curve;
        private CurveEditor m_CurveEditor;
        private AnimationCurve[] m_Presets;
        internal static Styles ms_Styles;
        private static CurveEditorWindow s_SharedCurveEditor;

        private void DoUpdateCurve(bool exitGUI)
        {
            if (((this.m_CurveEditor.animationCurves.Length > 0) && (this.m_CurveEditor.animationCurves[0] != null)) && this.m_CurveEditor.animationCurves[0].changed)
            {
                this.m_CurveEditor.animationCurves[0].changed = false;
                this.SendEvent("CurveChanged", exitGUI);
            }
        }

        private void DoWrapperPopups()
        {
            if ((this.m_Curve != null) && (this.m_Curve.length >= 2))
            {
                Color contentColor = GUI.contentColor;
                GUI.contentColor = Color.white;
                float width = 60f;
                Keyframe keyframe = this.m_Curve.keys[0];
                Vector3 lhs = new Vector3(keyframe.time, keyframe.value);
                lhs = this.m_CurveEditor.DrawingToViewTransformPoint(lhs);
                Rect position = new Rect((lhs.x - width) - 6f, lhs.y, width, 17f);
                WrapMode mode = (this.m_Curve == null) ? WrapMode.Default : this.m_Curve.preWrapMode;
                mode = (WrapMode) EditorGUI.EnumPopup(position, (WrapModeFixedCurve) mode, ms_Styles.curveWrapPopup);
                if ((this.m_Curve != null) && (mode != this.m_Curve.preWrapMode))
                {
                    this.m_Curve.preWrapMode = mode;
                    this.RefreshShownCurves();
                    this.SendEvent("CurveChanged", true);
                }
                keyframe = this.m_Curve.keys[this.m_Curve.length - 1];
                lhs = new Vector3(keyframe.time, keyframe.value);
                lhs = this.m_CurveEditor.DrawingToViewTransformPoint(lhs);
                position = new Rect(lhs.x + 6f, lhs.y, width, 17f);
                mode = (this.m_Curve == null) ? WrapMode.Default : this.m_Curve.postWrapMode;
                mode = (WrapMode) EditorGUI.EnumPopup(position, (WrapModeFixedCurve) mode, ms_Styles.curveWrapPopup);
                if ((this.m_Curve != null) && (mode != this.m_Curve.postWrapMode))
                {
                    this.m_Curve.postWrapMode = mode;
                    this.RefreshShownCurves();
                    this.SendEvent("CurveChanged", true);
                }
                GUI.contentColor = contentColor;
            }
        }

        private Rect GetCurveEditorRect()
        {
            return new Rect(0f, 0f, base.position.width, base.position.height - 46f);
        }

        private CurveWrapper[] GetCurveWrapperArray()
        {
            if (this.m_Curve == null)
            {
                return new CurveWrapper[0];
            }
            CurveWrapper wrapper = new CurveWrapper {
                id = "Curve".GetHashCode(),
                groupId = -1,
                color = this.m_Color,
                hidden = false,
                readOnly = false,
                renderer = new NormalCurveRenderer(this.m_Curve)
            };
            wrapper.renderer.SetWrap(this.m_Curve.preWrapMode, this.m_Curve.postWrapMode);
            return new CurveWrapper[] { wrapper };
        }

        internal static Keyframe[] GetEaseInKeys()
        {
            Keyframe[] keys = new Keyframe[] { new Keyframe(0f, 0f, 0f, 0f), new Keyframe(1f, 1f, 2f, 2f) };
            SetSmoothEditable(ref keys);
            return keys;
        }

        internal static Keyframe[] GetEaseInMirrorKeys()
        {
            Keyframe[] keys = new Keyframe[] { new Keyframe(0f, 1f, -2f, -2f), new Keyframe(1f, 0f, 0f, 0f) };
            SetSmoothEditable(ref keys);
            return keys;
        }

        internal static Keyframe[] GetEaseInOutKeys()
        {
            Keyframe[] keys = new Keyframe[] { new Keyframe(0f, 0f, 0f, 0f), new Keyframe(1f, 1f, 0f, 0f) };
            SetSmoothEditable(ref keys);
            return keys;
        }

        internal static Keyframe[] GetEaseInOutMirrorKeys()
        {
            Keyframe[] keys = new Keyframe[] { new Keyframe(0f, 1f, 0f, 0f), new Keyframe(1f, 0f, 0f, 0f) };
            SetSmoothEditable(ref keys);
            return keys;
        }

        internal static Keyframe[] GetEaseOutKeys()
        {
            Keyframe[] keys = new Keyframe[] { new Keyframe(0f, 0f, 2f, 2f), new Keyframe(1f, 1f, 0f, 0f) };
            SetSmoothEditable(ref keys);
            return keys;
        }

        internal static Keyframe[] GetEaseOutMirrorKeys()
        {
            Keyframe[] keys = new Keyframe[] { new Keyframe(0f, 1f, 0f, 0f), new Keyframe(1f, 0f, -2f, -2f) };
            SetSmoothEditable(ref keys);
            return keys;
        }

        internal static Keyframe[] GetLinearKeys()
        {
            Keyframe[] keyframeArray = new Keyframe[] { new Keyframe(0f, 0f, 1f, 1f), new Keyframe(1f, 1f, 1f, 1f) };
            for (int i = 0; i < 2; i++)
            {
                CurveUtility.SetKeyBroken(ref keyframeArray[i], false);
                CurveUtility.SetKeyTangentMode(ref keyframeArray[i], 0, TangentMode.Smooth);
                CurveUtility.SetKeyTangentMode(ref keyframeArray[i], 1, TangentMode.Smooth);
            }
            return keyframeArray;
        }

        internal static Keyframe[] GetLinearMirrorKeys()
        {
            Keyframe[] keyframeArray = new Keyframe[] { new Keyframe(0f, 1f, -1f, -1f), new Keyframe(1f, 0f, -1f, -1f) };
            for (int i = 0; i < 2; i++)
            {
                CurveUtility.SetKeyBroken(ref keyframeArray[i], false);
                CurveUtility.SetKeyTangentMode(ref keyframeArray[i], 0, TangentMode.Smooth);
                CurveUtility.SetKeyTangentMode(ref keyframeArray[i], 1, TangentMode.Smooth);
            }
            return keyframeArray;
        }

        internal static Keyframe[] GetOneKeys()
        {
            Keyframe[] keys = new Keyframe[] { new Keyframe(0f, 1f, 0f, 0f), new Keyframe(1f, 1f, 0f, 0f) };
            SetSmoothEditable(ref keys);
            return keys;
        }

        private void Init(CurveEditorSettings settings)
        {
            this.m_CurveEditor = new CurveEditor(this.GetCurveEditorRect(), this.GetCurveWrapperArray(), true);
            this.m_CurveEditor.curvesUpdated = new CurveEditor.CallbackFunction(this.UpdateCurve);
            this.m_CurveEditor.scaleWithWindow = true;
            this.m_CurveEditor.margin = 40f;
            if (settings != null)
            {
                this.m_CurveEditor.settings = settings;
            }
            this.m_CurveEditor.settings.hTickLabelOffset = 10f;
            this.m_CurveEditor.FrameSelected(true, true);
            this.m_Presets = new AnimationCurve[5];
            for (int i = 0; i < this.m_Presets.Length; i++)
            {
                this.m_Presets[i] = new AnimationCurve();
            }
            this.m_Presets[0].keys = GetOneKeys();
            this.m_Presets[1].keys = GetLinearKeys();
            this.m_Presets[2].keys = GetEaseInKeys();
            this.m_Presets[3].keys = GetEaseOutKeys();
            this.m_Presets[4].keys = GetEaseInOutKeys();
        }

        private void OnDisable()
        {
            this.m_CurveEditor.OnDisable();
            if (s_SharedCurveEditor == this)
            {
                s_SharedCurveEditor = null;
            }
            else if (!this.Equals(s_SharedCurveEditor))
            {
                throw new ApplicationException("s_SharedCurveEditor does not equal this");
            }
        }

        private void OnEnable()
        {
            s_SharedCurveEditor = this;
            this.Init(null);
            this.m_CurveEditor.OnEnable();
        }

        private void OnGUI()
        {
            bool flag = Event.current.type == EventType.MouseUp;
            if (this.delegateView == null)
            {
                this.m_Curve = null;
            }
            if (ms_Styles == null)
            {
                ms_Styles = new Styles();
            }
            this.m_CurveEditor.rect = this.GetCurveEditorRect();
            this.m_CurveEditor.hRangeLocked = Event.current.shift;
            this.m_CurveEditor.vRangeLocked = EditorGUI.actionKey;
            GUI.changed = false;
            GUI.Label(this.m_CurveEditor.drawRect, GUIContent.none, ms_Styles.curveEditorBackground);
            this.m_CurveEditor.BeginViewGUI();
            this.m_CurveEditor.GridGUI();
            this.m_CurveEditor.CurveGUI();
            this.DoWrapperPopups();
            this.m_CurveEditor.EndViewGUI();
            GUI.Box(new Rect(0f, base.position.height - 46f, base.position.width, 46f), string.Empty, ms_Styles.curveSwatchArea);
            Color color = this.m_Color;
            color.a *= 0.6f;
            for (int i = 0; i < this.m_Presets.Length; i++)
            {
                Rect position = new Rect((float) (6 + (0x30 * i)), (base.position.height - 46f) + 5f, 40f, 35f);
                if (GUI.Button(position, string.Empty, ms_Styles.curveSwatch))
                {
                    this.m_Curve.keys = this.m_Presets[i].keys;
                    this.m_CurveEditor.SelectNone();
                    this.SendEvent("CurveChanged", true);
                }
                EditorGUIUtility.DrawCurveSwatch(ms_Styles.curveSwatch.padding.Remove(position), this.m_Presets[i], null, color, Color.clear);
            }
            if ((Event.current.type == EventType.Used) && flag)
            {
                this.DoUpdateCurve(false);
                this.SendEvent("CurveChangeCompleted", true);
            }
            else if ((Event.current.type != EventType.Layout) && (Event.current.type != EventType.Repaint))
            {
                this.DoUpdateCurve(true);
            }
        }

        private void RefreshShownCurves()
        {
            this.m_CurveEditor.animationCurves = this.GetCurveWrapperArray();
        }

        private void SendEvent(string eventName, bool exitGUI)
        {
            if (this.delegateView != null)
            {
                Event e = EditorGUIUtility.CommandEvent(eventName);
                base.Repaint();
                this.delegateView.SendEvent(e);
                if (exitGUI)
                {
                    GUIUtility.ExitGUI();
                }
            }
            GUI.changed = true;
        }

        internal static void SetSmoothEditable(ref Keyframe[] keys)
        {
            for (int i = 0; i < keys.Length; i++)
            {
                CurveUtility.SetKeyBroken(ref keys[i], false);
                CurveUtility.SetKeyTangentMode(ref keys[i], 0, TangentMode.Editable);
                CurveUtility.SetKeyTangentMode(ref keys[i], 1, TangentMode.Editable);
            }
        }

        public void Show(GUIView viewToUpdate, CurveEditorSettings settings)
        {
            this.delegateView = viewToUpdate;
            this.Init(settings);
            base.ShowAuxWindow();
            base.title = "Curve";
            base.minSize = new Vector2(240f, 286f);
            base.maxSize = new Vector2(10000f, 10000f);
        }

        public void UpdateCurve()
        {
            this.DoUpdateCurve(false);
        }

        public static Color color
        {
            get
            {
                return instance.m_Color;
            }
            set
            {
                instance.m_Color = value;
                instance.RefreshShownCurves();
            }
        }

        public static AnimationCurve curve
        {
            get
            {
                return instance.m_Curve;
            }
            set
            {
                if (value == null)
                {
                    instance.m_Curve = null;
                }
                else
                {
                    instance.m_Curve = value;
                    instance.RefreshShownCurves();
                }
            }
        }

        public static CurveEditorWindow instance
        {
            get
            {
                if (s_SharedCurveEditor == null)
                {
                    s_SharedCurveEditor = ScriptableObject.CreateInstance<CurveEditorWindow>();
                }
                return s_SharedCurveEditor;
            }
        }

        public static bool visible
        {
            get
            {
                return (s_SharedCurveEditor != null);
            }
        }

        internal class Styles
        {
            public GUIStyle curveEditorBackground = "PopupCurveEditorBackground";
            public GUIStyle curveSwatch = "PopupCurveEditorSwatch";
            public GUIStyle curveSwatchArea = "PopupCurveSwatchBackground";
            public GUIStyle curveWrapPopup = "PopupCurveDropdown";
            public GUIStyle miniToolbarButton = "MiniToolbarButtonLeft";
            public GUIStyle miniToolbarPopup = "MiniToolbarPopup";
        }
    }
}

